package com.data.app.commons.exception.handler;

import com.data.app.commons.exception.BaseServiceException;
import com.data.app.commons.exception.BusinessServiceException;
import com.data.app.commons.exception.ParamServiceException;
import com.data.app.commons.exception.PermissionServiceException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;

/**
 * @Author Zyl
 * @Date 2021/3/30 15:11
 * @Version 1.0
 * @Describe: 全局的异常处理器拦截异常响应到前端
 */
//表示全局的异常通知，里面的value属性可以指定一个异常通知的包范围，一般这个不用去指定，就让他对全部的包进行扫描即可；
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @Resource
    private ObjectMapper jsonMapper;

    //加在方法上，表示要拦截的某个异常并对该异常进行处理，里面的参数是要拦截的异常的类型
    // 我这里拦截的是BaseServiceException这个异常，如果程序中有抛出BaseServiceException的地方就会进入该方法进行处理。
    @ExceptionHandler(BaseServiceException.class)
    public ObjectNode baseServiceException(BaseServiceException be){
        int code = be.getCode();
        String msg = be.getMessage();
        System.out.println("cause"+be.toString());
        log.error("BaseException:Throwable异常信息:========>【{}】",be.getCause());
        return jsonMapper.createObjectNode().put("code",code).put("msg",msg);
    }

    /**
     * TODO 业务异常
     * @param bx
     * @return
     */
    @ExceptionHandler(BusinessServiceException.class)
    //@ResponseBody
    public BusinessServiceException businessException(BusinessServiceException bx) {
        // 获取异常堆栈信息
        Throwable cause = bx.getCause();
        if (cause != null) {
            String causeString = "";
            // 将Throwable转换成字符串
            Writer result = new StringWriter();
            PrintWriter printWriter = new PrintWriter(result);
            cause.printStackTrace(printWriter);
            causeString = result.toString();
            if (causeString.length() > 2000) {
                // 截取2000字符
                causeString = causeString.substring(0 , 2000);
                log.error("BusinessException:Throwable业务异常信息:========>【{}】", causeString);
                return bx;
            }
        }
        return bx;
    }

    /**
     * TODO 参数异常
     * @param px
     * @return
     */
    @ExceptionHandler(ParamServiceException.class)
    //@ResponseBody
    public ParamServiceException paramException(ParamServiceException px) {
        // 获取异常堆栈信息
        Throwable cause = px.getCause();
        if (cause != null) {
            String causeString = "";
            // 将Throwable转换成字符串
            Writer result = new StringWriter();
            PrintWriter printWriter = new PrintWriter(result);
            cause.printStackTrace(printWriter);
            causeString = result.toString();
            if (causeString.length() > 2000) {
                // 截取2000字符
                causeString = causeString.substring(0 , 2000);
                log.error("BusinessException:Throwable参数异常信息:========>【{}】", causeString);
            }
        }
        return px;
    }

    /**
     * TODO 权限异常
     * @param px
     * @return
     */
    @ExceptionHandler(PermissionServiceException.class)
    //@ResponseBody
    public PermissionServiceException prmissionException(PermissionServiceException px) {
        // 获取异常堆栈信息
        Throwable cause = px.getCause();
        if (cause != null) {
            String causeString = "";
            // 将Throwable转换成字符串
            Writer result = new StringWriter();
            PrintWriter printWriter = new PrintWriter(result);
            cause.printStackTrace(printWriter);
            causeString = result.toString();
            if (causeString.length() > 2000) {
                // 截取2000字符
                causeString = causeString.substring(0 , 2000);
                log.error("PermissionServiceException:Throwable权限异常信息:========>【{}】", causeString);
                return px;
            }
        }
        return px;
    }

}
